/*
 * BoardTest.c
 *
 *  Created on: Dec 7, 2012
 *      Author: Larry.Li
 */

#include "TestUtils.h"
#include "../BitBoard.h"
#include "../BitBoardOps.h"

int initBitBoardTestSuite(void) {
	initBoard();
	return 0;
}
int cleanBitBoardTestSuite(void) {
	return 0;
}

void test_maskInitialization() {
	int bitArray[90];
	int i;
	for (i = 0; i < 90; i++) {
		genBitBoardArrayMapping(&mask[i], bitArray);
		CU_ASSERT_EQUAL(bitArray[i], 1);
	}
}

void test_rotateMaskInitialization() {
	int bitArray[90];
	int i, j;
	for (i = 0; i < 9; i++) {
		for (j = 0; j < 10; j++) {
			genBitBoardArrayMapping(&rotateMask[j * 9 + i], bitArray);
			CU_ASSERT_EQUAL(bitArray[(8 - i) * 10 + j], 1);
		}
	}
}

void test_jiangMovements() {
	int bitArray[90];
	int i, j, chessPos, possiblePos;
	for (i = 3; i <= 5; i++) {
		for (j = 0; j <= 2; j++) {
			chessPos = j * 9 + i;
			genBitBoardArrayMapping(&MOVEMENTS.jiang[chessPos], bitArray);
			possiblePos = 0;
			if (i > 3) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos - 1], 1);
			}
			if (i < 5) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos + 1], 1);
			}
			if (j > 0) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos - 9], 1);
			}
			if (j < 2) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos + 9], 1);
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.jiang[chessPos]),
					possiblePos);

		}
		for (j = 7; j <= 9; j++) {
			chessPos = j * 9 + i;
			genBitBoardArrayMapping(&MOVEMENTS.jiang[chessPos], bitArray);
			possiblePos = 0;
			if (i > 3) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos - 1], 1);
			}
			if (i < 5) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos + 1], 1);
			}
			if (j > 7) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos - 9], 1);
			}
			if (j < 9) {
				possiblePos += 1;
				CU_ASSERT_EQUAL(bitArray[chessPos + 9], 1);
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.jiang[chessPos]),
					possiblePos);
		}
	}
}

void test_xiangMovements() {
	int bitArray[90];
	int rowBits[512][9];
	genAllPossibleBitArrayOfRank(rowBits);
	int i, j, xiangIndex, xiangRankPos, goingTopRowIndex, goingBottomRowIndex,
			possiblePos;
	for (i = 0; i < 90; i++) {
		xiangIndex = MOVEMENTS.xiangIndexMapping[i];
		if (xiangIndex == INVALID_POS) {
			continue;
		}
		xiangRankPos = indexRankBitsPositionMapping[i];
		goingTopRowIndex = MOVEMENTS.xiangGoingTopRowMapping[i];
		goingBottomRowIndex = MOVEMENTS.xiangGoingBottomRowMapping[i];
		for (j = 0; j < 512; j++) {
			possiblePos = 0;
			if (goingTopRowIndex != INVALID_POS) {
				genBitBoardArrayMapping(&MOVEMENTS.xiangGoingTop[xiangIndex][j],
						bitArray);
				if (xiangRankPos >= 2) {
					if (rowBits[j][xiangRankPos - 1]) {
						CU_ASSERT_EQUAL(bitArray[i + 16], 0);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + 16], 1);
						possiblePos++;
					}
				}
				if (xiangRankPos <= 6) {
					if (rowBits[j][xiangRankPos + 1]) {
						CU_ASSERT_EQUAL(bitArray[i + 20], 0);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + 20], 1);
						possiblePos++;
					}
				}
				CU_ASSERT_EQUAL(
						countBitBoardTotalBits(&MOVEMENTS.xiangGoingTop[xiangIndex][j]),
						possiblePos);
			}

			possiblePos = 0;
			if (goingBottomRowIndex != INVALID_POS) {
				genBitBoardArrayMapping(
						&MOVEMENTS.xiangGoingBottom[xiangIndex][j], bitArray);
				if (xiangRankPos >= 2) {
					if (rowBits[j][xiangRankPos - 1] == 1) {
						CU_ASSERT_EQUAL(bitArray[i - 20], 0);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - 20], 1);
						possiblePos++;
					}
				}
				if (xiangRankPos <= 6) {
					if (rowBits[j][xiangRankPos + 1] == 1) {
						CU_ASSERT_EQUAL(bitArray[i - 16], 0);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - 16], 1);
						possiblePos++;
					}
				}
				CU_ASSERT_EQUAL(
						countBitBoardTotalBits(&MOVEMENTS.xiangGoingBottom[xiangIndex][j]),
						possiblePos);
			}
		}

	}
}

void test_shiMovements() {
	int bitArray[90];
	//red shi
	genBitBoardArrayMapping(&MOVEMENTS.shi[3], bitArray);
	CU_ASSERT_EQUAL(bitArray[13], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[3]), 1);

	genBitBoardArrayMapping(&MOVEMENTS.shi[5], bitArray);
	CU_ASSERT_EQUAL(bitArray[13], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[5]), 1);

	genBitBoardArrayMapping(&MOVEMENTS.shi[13], bitArray);
	CU_ASSERT_EQUAL(bitArray[3], 1);
	CU_ASSERT_EQUAL(bitArray[5], 1);
	CU_ASSERT_EQUAL(bitArray[21], 1);
	CU_ASSERT_EQUAL(bitArray[23], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[13]), 4);

	genBitBoardArrayMapping(&MOVEMENTS.shi[21], bitArray);
	CU_ASSERT_EQUAL(bitArray[13], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[21]), 1);

	genBitBoardArrayMapping(&MOVEMENTS.shi[23], bitArray);
	CU_ASSERT_EQUAL(bitArray[13], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[23]), 1);

	//black shi
	genBitBoardArrayMapping(&MOVEMENTS.shi[66], bitArray);
	CU_ASSERT_EQUAL(bitArray[76], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[66]), 1);

	genBitBoardArrayMapping(&MOVEMENTS.shi[68], bitArray);
	CU_ASSERT_EQUAL(bitArray[76], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[68]), 1);

	genBitBoardArrayMapping(&MOVEMENTS.shi[76], bitArray);
	CU_ASSERT_EQUAL(bitArray[66], 1);
	CU_ASSERT_EQUAL(bitArray[68], 1);
	CU_ASSERT_EQUAL(bitArray[84], 1);
	CU_ASSERT_EQUAL(bitArray[86], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[76]), 4);

	genBitBoardArrayMapping(&MOVEMENTS.shi[84], bitArray);
	CU_ASSERT_EQUAL(bitArray[76], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[84]), 1);

	genBitBoardArrayMapping(&MOVEMENTS.shi[86], bitArray);
	CU_ASSERT_EQUAL(bitArray[76], 1);
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.shi[86]), 1);
}

void test_redBingMovements() {
	int bitArray[90];
	int i, possiblePos, bingRankPos;
	for (i = 27; i < 90; i++) {
		possiblePos = 0;
		genBitBoardArrayMapping(&MOVEMENTS.r_bing[i], bitArray);
		bingRankPos = indexRankBitsPositionMapping[i];
		if (i <= 80) {
			possiblePos++;
			CU_ASSERT_EQUAL(bitArray[i + 9], 1);
		}
		if (i >= 45) {
			if (bingRankPos > 0) {
				possiblePos++;
				CU_ASSERT_EQUAL(bitArray[i - 1], 1);
			}
			if (bingRankPos < 8) {
				possiblePos++;
				CU_ASSERT_EQUAL(bitArray[i + 1], 1);
			}
		}
		CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.r_bing[i]),
				possiblePos);
	}
}

void test_blackBingMovements() {
	int bitArray[90];
	int i, possiblePos, bingRankPos;
	for (i = 0; i < 45; i++) {
		possiblePos = 0;
		genBitBoardArrayMapping(&MOVEMENTS.b_bing[i], bitArray);
		bingRankPos = indexRankBitsPositionMapping[i];
		if (i >= 9) {
			possiblePos++;
			CU_ASSERT_EQUAL(bitArray[i - 9], 1);
		}
		if (i <= 44) {
			if (bingRankPos > 0) {
				possiblePos++;
				CU_ASSERT_EQUAL(bitArray[i - 1], 1);
			}
			if (bingRankPos < 8) {
				possiblePos++;
				CU_ASSERT_EQUAL(bitArray[i + 1], 1);
			}
		}
		CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.b_bing[i]),
				possiblePos);
	}
}

void test_cheMovements() {
	int bitArray[90];
	int rankRowBits[512][9];
	genAllPossibleBitArrayOfRank(rankRowBits);
	int fileRowBits[1024][10];
	genAllPossibleBitArrayOfFile(fileRowBits);

	int i, j, k, cheRankPos, cheFilePos, accessible, possiblePos;

	for (i = 0; i < 90; i++) {
		//rank movement
		cheRankPos = indexRankBitsPositionMapping[i];
		for (j = 0; j < 512; j++) {
			genBitBoardArrayMapping(&MOVEMENTS.cheRank[i][j], bitArray);
			if (rankRowBits[j][cheRankPos] == 0) {
				continue;
			}
			possiblePos = 0;
			//leftward
			accessible = 1;
			for (k = 1; k < 9 - cheRankPos; k++) {
				if (accessible) {
					CU_ASSERT_EQUAL(bitArray[i + k], 1);
					possiblePos++;
					if (rankRowBits[j][k + cheRankPos]) {
						accessible = 0;
					}
				} else {
					CU_ASSERT_EQUAL(bitArray[i + k], 0);
				}
			}

			//rightward
			accessible = 1;
			for (k = 1; k <= cheRankPos; k++) {
				if (accessible) {
					CU_ASSERT_EQUAL(bitArray[i - k], 1);
					possiblePos++;
					if (rankRowBits[j][cheRankPos - k]) {
						accessible = 0;
					}
				} else {
					CU_ASSERT_EQUAL(bitArray[i - k], 0);
				}
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.cheRank[i][j]),
					possiblePos);
		}
		//file movements
		cheFilePos = indexRowMapping[i];
		for (j = 0; j < 1024; j++) {
			genBitBoardArrayMapping(&MOVEMENTS.cheFile[i][j], bitArray);
			if (fileRowBits[j][cheFilePos] == 0) {
				continue;
			}
			possiblePos = 0;
			//upward
			accessible = 1;
			for (k = 1; k < 10 - cheFilePos; k++) {
				if (accessible) {
					CU_ASSERT_EQUAL(bitArray[i + k * 9], 1);
					possiblePos++;
					if (fileRowBits[j][k + cheFilePos]) {
						accessible = 0;
					}
				} else {
					CU_ASSERT_EQUAL(bitArray[i + k * 9], 0);
				}
			}

			//downward
			accessible = 1;
			for (k = 1; k <= cheFilePos; k++) {
				if (accessible) {
					CU_ASSERT_EQUAL(bitArray[i - k * 9], 1);
					possiblePos++;
					if (fileRowBits[j][cheFilePos - k]) {
						accessible = 0;
					}
				} else {
					CU_ASSERT_EQUAL(bitArray[i - k * 9], 0);
				}
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.cheFile[i][j]),
					possiblePos);
		}
	}

}

void test_maMovements() {
	int rankRowBits[512][9];
	genAllPossibleBitArrayOfRank(rankRowBits);

	int fileRowBits[1024][10];
	genAllPossibleBitArrayOfFile(fileRowBits);

	int bitArray[90];
	int i, j, maRankPos, maFilePos, possiblePos;
	for (i = 0; i < 90; i++) {
		maRankPos = indexRankBitsPositionMapping[i];
		//rank movement
		for (j = 0; j < 512; j++) {
			genBitBoardArrayMapping(&MOVEMENTS.maRank[i][j], bitArray);
			if (rankRowBits[j][maRankPos] == 0)
				continue;

			possiblePos = 0;
			if (maRankPos > 1) {
				if ((i + 7) < 90) {
					if (rankRowBits[j][maRankPos - 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i + 7], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + 7], 0);
					}
				}
				if ((i - 11) >= 0) {
					if (rankRowBits[j][maRankPos - 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i - 11], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - 11], 0);
					}
				}
			}
			if (maRankPos < 7) {
				if ((i + 11) < 90) {
					if (rankRowBits[j][maRankPos + 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i + 11], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + 11], 0);
					}
				}
				if ((i - 7) >= 0) {
					if (rankRowBits[j][maRankPos + 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i - 7], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - 7], 0);
					}

				}
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.maRank[i][j]),
					possiblePos);
		}
		maFilePos = indexRowMapping[i];
		//file movement
		for (j = 0; j < 1024; j++) {
			genBitBoardArrayMapping(&MOVEMENTS.maFile[i][j], bitArray);
			if (fileRowBits[j][maFilePos] == 0)
				continue;

			possiblePos = 0;
			if (maFilePos > 0) {
				if ((i + 17) < 90) {
					if (fileRowBits[j][maFilePos + 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i + 17], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + 17], 0);
					}
				}
				if ((i - 19) >= 0) {
					if (fileRowBits[j][maFilePos - 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i - 19], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - 19], 0);
					}
				}
			}
			if (maFilePos < 8) {
				if ((i + 19) < 90) {
					if (fileRowBits[j][maFilePos + 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i + 19], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + 19], 0);
					}
				}
				if ((i - 17) >= 0) {
					if (fileRowBits[j][maFilePos - 1] == 0) {
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i - 17], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - 17], 0);
					}
				}
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.maFile[i][j]),
					possiblePos);
		}
	}
}

void test_paoMovements() {
	int bitArray[90];
	int rankRowBits[512][9];
	genAllPossibleBitArrayOfRank(rankRowBits);
	int fileRowBits[1024][10];
	genAllPossibleBitArrayOfFile(fileRowBits);

	int i, j, k, paoRankPos, paoFilePos, accessible, attackPositionHaventMarked,
			possiblePos;

	for (i = 0; i < 90; i++) {
		//rank movement
		paoRankPos = indexRankBitsPositionMapping[i];
		for (j = 0; j < 512; j++) {
			genBitBoardArrayMapping(&MOVEMENTS.paoRank[i][j], bitArray);
			if (rankRowBits[j][paoRankPos] == 0) {
				continue;
			}
			possiblePos = 0;
			//leftward
			accessible = 1;
			attackPositionHaventMarked = 1;
			for (k = 1; k < 9 - paoRankPos; k++) {
				if (accessible) {
					if (rankRowBits[j][k + paoRankPos] == 0) {
						CU_ASSERT_EQUAL(bitArray[i + k], 1);
						possiblePos++;
					} else {
						CU_ASSERT_EQUAL(bitArray[i + k], 0);
						accessible = 0;
					}
				} else {
					if (attackPositionHaventMarked
							&& (rankRowBits[j][k + paoRankPos] == 1)) {
						attackPositionHaventMarked = 0;
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i + k], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + k], 0);
					}
				}
			}

			//rightward
			attackPositionHaventMarked = 1;
			accessible = 1;
			for (k = 1; k <= paoRankPos; k++) {
				if (accessible) {
					if (rankRowBits[j][paoRankPos - k] == 0) {
						CU_ASSERT_EQUAL(bitArray[i - k], 1);
						possiblePos++;
					} else {
						CU_ASSERT_EQUAL(bitArray[i - k], 0);
						accessible = 0;
					}
				} else {
					if (attackPositionHaventMarked
							&& (rankRowBits[j][paoRankPos - k] == 1)) {
						attackPositionHaventMarked = 0;
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i - k], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - k], 0);
					}
				}
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.paoRank[i][j]),
					possiblePos);
		}
//		file movements
		paoFilePos = indexRowMapping[i];
		for (j = 0; j < 1024; j++) {
			genBitBoardArrayMapping(&MOVEMENTS.paoFile[i][j], bitArray);
			if (fileRowBits[j][paoFilePos] == 0) {
				continue;
			}
			possiblePos = 0;
//			upward
			accessible = 1;
			attackPositionHaventMarked = 1;
			for (k = 1; k < 10 - paoFilePos; k++) {
				if (accessible) {
					if (fileRowBits[j][k + paoFilePos] == 0) {
						CU_ASSERT_EQUAL(bitArray[i + k * 9], 1);
						possiblePos++;
					} else {
						CU_ASSERT_EQUAL(bitArray[i + k * 9], 0);
						accessible = 0;
					}
				} else {
					if (attackPositionHaventMarked
							&& (fileRowBits[j][k + paoFilePos] == 1)) {
						attackPositionHaventMarked = 0;
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i + k * 9], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i + k * 9], 0);
					}

				}
			}

			//downward
			accessible = 1;
			attackPositionHaventMarked = 1;
			for (k = 1; k <= paoFilePos; k++) {
				if (accessible) {
					if (fileRowBits[j][paoFilePos - k] == 0) {
						CU_ASSERT_EQUAL(bitArray[i - k * 9], 1);
						possiblePos++;
					} else {
						CU_ASSERT_EQUAL(bitArray[i - k * 9], 0);
						accessible = 0;
					}
				} else {
					if (attackPositionHaventMarked
							&& (fileRowBits[j][paoFilePos - k] == 1)) {
						attackPositionHaventMarked = 0;
						possiblePos++;
						CU_ASSERT_EQUAL(bitArray[i - k * 9], 1);
					} else {
						CU_ASSERT_EQUAL(bitArray[i - k * 9], 0);
					}
				}
			}
			CU_ASSERT_EQUAL(countBitBoardTotalBits(&MOVEMENTS.paoFile[i][j]),
					possiblePos);
		}
	}
}
extern int genRedJiangKillingMovements(ChessPosition*, Movement*);
void test_genRedJiangKillingMovements() {
	Movement movements[194];
	ChessPosition chessPosition;
	int fileBits[1024][10];
	genAllPossibleBitArrayOfFile(fileBits);
	int file, rank, opponentJiangFile, opponentJiangRank, movementCount, up,
			down, left, right, chessPos, opponentJiangPos, possiblePos;
	unsigned long fileBitsPossiblities;
	for (file = 3; file <= 5; file++) {
		for (rank = 0; rank <= 2; rank++) {
			chessPos = rank * 9 + file;
			for (up = 0; up < 1; up++) {
				for (right = 0; right < 1; right++) {
					for (down = 0; down < 1; down++) {
						for (left = 0; left < 1; left++) {
							for (opponentJiangFile = 3; opponentJiangFile <= 5;
									opponentJiangFile++) {
								for (opponentJiangRank = 7;
										opponentJiangRank < 10;
										opponentJiangRank++) {
									for (fileBitsPossiblities = 0;
											fileBitsPossiblities < 1024;
											fileBitsPossiblities++) {

										if (!fileBits[fileBitsPossiblities][rank]) {
											//this file chess status is not a valid status because red jiang doesn't exists
											continue;
										}

										if ((file == opponentJiangFile)
												&& (!fileBits[fileBitsPossiblities][opponentJiangRank])) {
											//this file chess status is not a valid status because black jiang doesn't exists
											continue;
										}
										opponentJiangPos = opponentJiangRank * 9
												+ opponentJiangFile;

										BITBOARD_ANDEMPTY(
												chessPosition.r_jiang);
										BITBOARD_ANDEMPTY(
												chessPosition.r_pieces);
										BITBOARD_ANDEMPTY(
												chessPosition.b_pieces);
										BITBOARD_ANDEMPTY(
												chessPosition.b_jiang);

										chessPosition.all_pieces =
												getFileBitBoardFromLowest10Bits(
														fileBitsPossiblities,
														file);

										setChessPosition(BJ, opponentJiangPos,
												&chessPosition);
										setChessPosition(RJ, chessPos,
												&chessPosition);

										if (rank < 2
												|| (rank >= 7 && rank < 9)) {
											if (up
													&& fileBits[fileBitsPossiblities][rank
															+ 1]) {
												BITBOARD_OR(
														chessPosition.b_pieces,
														mask[chessPos + 9]);
											}
										}
										if (file > 3) {
											if (right) {
												BITBOARD_OR(
														chessPosition.b_pieces,
														mask[chessPos - 1]);
												BITBOARD_OR(
														chessPosition.all_pieces,
														mask[chessPos - 1]);
											}
										}
										if ((rank > 0 && rank <= 2)
												|| rank >= 8) {
											if (down) {
												BITBOARD_OR(
														chessPosition.b_pieces,
														mask[chessPos - 9]);
											}
										}
										if (file < 5) {
											if (left) {
												BITBOARD_OR(
														chessPosition.b_pieces,
														mask[chessPos + 1]);
												BITBOARD_OR(
														chessPosition.all_pieces,
														mask[chessPos + 1]);
											} else {
												BITBOARD_ANDNOT(
														chessPosition.b_pieces,
														mask[chessPos + 1]);
												BITBOARD_ANDNOT(
														chessPosition.all_pieces,
														mask[chessPos + 1]);
											}
										}
										movementCount =
												genRedJiangKillingMovements(
														&chessPosition,
														movements);

										possiblePos = 0;
										if (rank < 2
												|| (rank >= 7 && rank < 9)) {
											possiblePos += up;
											CU_ASSERT_EQUAL(
													isMovementExists(movements, movementCount, chessPos, chessPos + 9),
													up);
										}
										if ((rank > 0 && rank <= 2)
												|| rank >= 8) {
											possiblePos += down;
											CU_ASSERT_EQUAL(
													isMovementExists(movements, movementCount, chessPos, chessPos - 9),
													down);
										}
										if (file > 3) {
											possiblePos += right;
											CU_ASSERT_EQUAL(
													isMovementExists(movements, movementCount, chessPos, chessPos - 1),
													right);
										}
										if (file < 5) {
											possiblePos += left;
											CU_ASSERT_EQUAL(
													isMovementExists(movements, movementCount, chessPos, chessPos + 1),
													left);
										}
										//killing opponent jiang
										if (opponentJiangFile == file) {
											int i = rank + 1;
											int hasPieceBetweenTwoJiangs = 0;
											for (; i < opponentJiangRank; i++) {
												if (fileBits[fileBitsPossiblities][i]) {
													hasPieceBetweenTwoJiangs =
															1;
													break;
												}
											}
											if (hasPieceBetweenTwoJiangs) {
												CU_ASSERT_EQUAL(
														isMovementExists( movements, movementCount, chessPos, opponentJiangPos),
														0);
											} else {
												possiblePos++;
												CU_ASSERT_EQUAL(
														isMovementExists(movements, movementCount, chessPos, opponentJiangPos),
														1);
											}
										}
										CU_ASSERT_EQUAL(movementCount,
												possiblePos);
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

extern int genRedXiangKillingMovements(ChessPosition*, Movement*);
void test_genRedXiangKillingMovements() {
	ChessPosition chessPosition;
	Movement movements[194];
	int rowBits[512][9];
	genAllPossibleBitArrayOfRank(rowBits);

	BitBoard tempBoard;
	int xiangPos, topLeft, topRight, bottomLeft, bottomRight, xiangIndex,
			xiangRankPos, goingTopRowIndex, goingBottomRowIndex, possiblePos,
			movementCount;
	unsigned long topRowBitsPossiblities, bottomRowBitsPossiblities;

	for (xiangPos = 0; xiangPos < 43; xiangPos++) {
		xiangIndex = MOVEMENTS.xiangIndexMapping[xiangPos];
		if (xiangIndex == INVALID_POS) {
			continue;
		}
		xiangRankPos = indexRankBitsPositionMapping[xiangPos];
		goingTopRowIndex = MOVEMENTS.xiangGoingTopRowMapping[xiangPos];
		goingBottomRowIndex = MOVEMENTS.xiangGoingBottomRowMapping[xiangPos];

		BITBOARD_ANDEMPTY(chessPosition.r_xiang);
		setChessPosition(RX, xiangPos, &chessPosition);

		for (topRowBitsPossiblities = 0; topRowBitsPossiblities < 512;
				topRowBitsPossiblities++) {
			for (bottomRowBitsPossiblities = 0; bottomRowBitsPossiblities < 512;
					bottomRowBitsPossiblities++) {
				for (topLeft = 0; topLeft < 2; topLeft++) {
					for (topRight = 0; topRight < 2; topRight++) {
						for (bottomLeft = 0; bottomLeft < 2; bottomLeft++) {
							for (bottomRight = 0; bottomRight < 2;
									bottomRight++) {

								BITBOARD_ANDEMPTY(chessPosition.b_pieces);
								BITBOARD_ANDEMPTY(chessPosition.all_pieces);

								if (goingTopRowIndex != INVALID_POS) {
									tempBoard = getRankBitBoardFromLowest9Bits(
											topRowBitsPossiblities,
											goingTopRowIndex);
									BITBOARD_OR(chessPosition.all_pieces,
											tempBoard);

									if (xiangRankPos >= 2 && topRight) {
										BITBOARD_OR(chessPosition.b_pieces,
												mask[xiangPos + 16]);
										BITBOARD_OR(chessPosition.all_pieces,
												mask[xiangPos + 16]);
									}
									if (xiangRankPos <= 6 && topLeft) {
										BITBOARD_OR(chessPosition.b_pieces,
												mask[xiangPos + 20]);
										BITBOARD_OR(chessPosition.all_pieces,
												mask[xiangPos + 20]);
									}
								}

								if (goingBottomRowIndex != INVALID_POS) {
									tempBoard = getRankBitBoardFromLowest9Bits(
											bottomRowBitsPossiblities,
											goingBottomRowIndex);
									BITBOARD_OR(chessPosition.all_pieces,
											tempBoard);

									if (xiangRankPos >= 2 && bottomRight) {
										BITBOARD_OR(chessPosition.b_pieces,
												mask[xiangPos - 20]);
										BITBOARD_OR(chessPosition.all_pieces,
												mask[xiangPos - 20]);
									}
									if (xiangRankPos <= 6 && bottomLeft) {
										BITBOARD_OR(chessPosition.b_pieces,
												mask[xiangPos - 16]);
										BITBOARD_OR(chessPosition.all_pieces,
												mask[xiangPos - 16]);
									}
								}
								possiblePos = 0;
								movementCount = genRedXiangKillingMovements(
										&chessPosition, movements);

								if (goingTopRowIndex != INVALID_POS) {
									if (xiangRankPos >= 2) {
										if (rowBits[topRowBitsPossiblities][xiangRankPos
												- 1]) {
											CU_ASSERT_EQUAL(
													isMovementExists(movements,movementCount,xiangPos,xiangPos + 16),
													0);
										} else {
											possiblePos += topRight;
											CU_ASSERT_EQUAL(
													isMovementExists(movements, movementCount, xiangPos, xiangPos + 16),
													topRight);
										}
									}
									if (xiangRankPos <= 6) {
										if (rowBits[topRowBitsPossiblities][xiangRankPos
												+ 1]) {
											CU_ASSERT_EQUAL(
													isMovementExists(movements,movementCount,xiangPos,xiangPos + 20),
													0);
										} else {
											possiblePos += topLeft;
											CU_ASSERT_EQUAL(
													isMovementExists(movements,movementCount,xiangPos,xiangPos + 20),
													topLeft);
										}
									}
								}
								if (goingBottomRowIndex != INVALID_POS) {
									if (xiangRankPos >= 2) {
										if (rowBits[bottomRowBitsPossiblities][xiangRankPos
												- 1]) {
											CU_ASSERT_EQUAL(
													isMovementExists(movements,movementCount,xiangPos,xiangPos - 20),
													0);
										} else {
											possiblePos += bottomRight;
											CU_ASSERT_EQUAL(
													isMovementExists(movements, movementCount, xiangPos, xiangPos - 20),
													bottomRight);

										}
									}
									if (xiangRankPos <= 6) {
										if (rowBits[bottomRowBitsPossiblities][xiangRankPos
												+ 1]) {
											CU_ASSERT_EQUAL(
													isMovementExists(movements,movementCount,xiangPos,xiangPos - 16),
													0);
										} else {
											possiblePos += bottomLeft;
											CU_ASSERT_EQUAL(
													isMovementExists(movements,movementCount,xiangPos,xiangPos - 16),
													bottomLeft);
										}
									}
								}
								CU_ASSERT_EQUAL(movementCount, possiblePos);
							}
						}
					}
				}
			}
		}
	}
}

extern int genRedShiKillingMovements(ChessPosition*, Movement*);
void test_genRedShiKillingMovements() {
	ChessPosition chessPosition;
	Movement movements[194];
	int rowBits[512][9];
	genAllPossibleBitArrayOfRank(rowBits);

	int movementCount;

	//in pos 3
	BITBOARD_ANDEMPTY(chessPosition.all_pieces);
	BITBOARD_ANDEMPTY(chessPosition.b_pieces);
	BITBOARD_ANDEMPTY(chessPosition.r_shi);
	BITBOARD_ANDEMPTY(chessPosition.r_pieces);

	setChessPosition(RS, 3, &chessPosition);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 0);

	BITBOARD_OR(chessPosition.b_pieces, mask[13]);
	BITBOARD_OR(chessPosition.all_pieces, mask[13]);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 1);
	CU_ASSERT_EQUAL(movements[0].from, 3);
	CU_ASSERT_EQUAL(movements[0].to, 13);

	//in pos 5
	BITBOARD_ANDEMPTY(chessPosition.all_pieces);
	BITBOARD_ANDEMPTY(chessPosition.b_pieces);
	BITBOARD_ANDEMPTY(chessPosition.r_shi);
	BITBOARD_ANDEMPTY(chessPosition.r_pieces);

	setChessPosition(RS, 5, &chessPosition);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 0);

	BITBOARD_OR(chessPosition.b_pieces, mask[13]);
	BITBOARD_OR(chessPosition.all_pieces, mask[13]);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 1);
	CU_ASSERT_EQUAL(movements[0].from, 5);
	CU_ASSERT_EQUAL(movements[0].to, 13);

	//in pos 13

	int rightTop, rightBottom, leftTop, leftBottom;
	for (rightTop = 0; rightTop < 2; rightTop++) {
		for (rightBottom = 0; rightBottom < 2; rightBottom++) {
			for (leftTop = 0; leftTop < 2; leftTop++) {
				for (leftBottom = 0; leftBottom < 2; leftBottom++) {

					BITBOARD_ANDEMPTY(chessPosition.all_pieces);
					BITBOARD_ANDEMPTY(chessPosition.b_pieces);
					BITBOARD_ANDEMPTY(chessPosition.r_shi);
					BITBOARD_ANDEMPTY(chessPosition.r_pieces);

					setChessPosition(RS, 13, &chessPosition);

					if (rightTop) {
						BITBOARD_OR(chessPosition.b_pieces, mask[21]);
						BITBOARD_OR(chessPosition.all_pieces, mask[21]);
					}
					if (rightBottom) {
						BITBOARD_OR(chessPosition.b_pieces, mask[3]);
						BITBOARD_OR(chessPosition.all_pieces, mask[3]);
					}
					if (leftTop) {
						BITBOARD_OR(chessPosition.b_pieces, mask[23]);
						BITBOARD_OR(chessPosition.all_pieces, mask[23]);
					}
					if (leftBottom) {
						BITBOARD_OR(chessPosition.b_pieces, mask[5]);
						BITBOARD_OR(chessPosition.all_pieces, mask[5]);
					}

					movementCount = genRedShiKillingMovements(&chessPosition,
							movements);
					CU_ASSERT_EQUAL(movementCount,
							rightTop + rightBottom + leftTop + leftBottom);

					CU_ASSERT_EQUAL(
							isMovementExists(movements,movementCount,13,21),
							rightTop);
					CU_ASSERT_EQUAL(
							isMovementExists(movements,movementCount,13,3),
							rightBottom);
					CU_ASSERT_EQUAL(
							isMovementExists(movements,movementCount,13,23),
							leftTop);
					CU_ASSERT_EQUAL(
							isMovementExists(movements,movementCount,13,5),
							leftBottom);

				}
			}
		}
	}

	//in pos 21
	BITBOARD_ANDEMPTY(chessPosition.all_pieces);
	BITBOARD_ANDEMPTY(chessPosition.b_pieces);
	BITBOARD_ANDEMPTY(chessPosition.r_shi);
	BITBOARD_ANDEMPTY(chessPosition.r_pieces);

	setChessPosition(RS, 21, &chessPosition);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 0);

	BITBOARD_OR(chessPosition.b_pieces, mask[13]);
	BITBOARD_OR(chessPosition.all_pieces, mask[13]);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 1);
	CU_ASSERT_EQUAL(movements[0].from, 21);
	CU_ASSERT_EQUAL(movements[0].to, 13);

	//in pos 23
	BITBOARD_ANDEMPTY(chessPosition.all_pieces);
	BITBOARD_ANDEMPTY(chessPosition.b_pieces);
	BITBOARD_ANDEMPTY(chessPosition.r_shi);
	BITBOARD_ANDEMPTY(chessPosition.r_pieces);

	setChessPosition(RS, 23, &chessPosition);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 0);

	BITBOARD_OR(chessPosition.b_pieces, mask[13]);
	BITBOARD_OR(chessPosition.all_pieces, mask[13]);

	movementCount = genRedShiKillingMovements(&chessPosition, movements);
	CU_ASSERT_EQUAL(movementCount, 1);
	CU_ASSERT_EQUAL(movements[0].from, 23);
	CU_ASSERT_EQUAL(movements[0].to, 13);
}

extern int genRedBingKillingMovements(ChessPosition*, Movement*);
void test_genRedBingKillingMovements() {
	int bingPos, bingRankPos, top, left, right, movementCount, possiblePos;
	Movement movements[194];
	ChessPosition chessPosition;

	for (bingPos = 27; bingPos < 90; bingPos++) {
		bingRankPos = indexRankBitsPositionMapping[bingPos];
		if (bingPos == 28 || bingPos == 30 || bingPos == 32 || bingPos == 34)
			continue;

		for (top = 0; top < 2; top++) {
			for (left = 0; left < 2; left++) {
				for (right = 0; right < 2; right++) {
					BITBOARD_ANDEMPTY(chessPosition.all_pieces);
					BITBOARD_ANDEMPTY(chessPosition.r_bing);
					BITBOARD_ANDEMPTY(chessPosition.r_pieces);
					BITBOARD_ANDEMPTY(chessPosition.b_pieces);

					setChessPosition(RB, bingPos, &chessPosition);

					possiblePos = 0;
					if (bingRankPos > 0 && bingPos > 45 && right) {
						possiblePos++;
						BITBOARD_OR(chessPosition.b_pieces, mask[bingPos - 1]);
						BITBOARD_OR(chessPosition.all_pieces,
								mask[bingPos - 1]);
					}
					if (bingRankPos < 8 && bingPos >= 45 && left) {
						possiblePos++;
						BITBOARD_OR(chessPosition.b_pieces, mask[bingPos + 1]);
						BITBOARD_OR(chessPosition.all_pieces,
								mask[bingPos + 1]);
					}
					if (bingPos < 81 && top) {
						possiblePos++;
						BITBOARD_OR(chessPosition.b_pieces, mask[bingPos + 9]);
						BITBOARD_OR(chessPosition.all_pieces,
								mask[bingPos + 9]);
					}

					movementCount = genRedBingKillingMovements(&chessPosition,
							movements);

					CU_ASSERT_EQUAL(movementCount, possiblePos);

					if (bingRankPos > 0 && bingPos > 45) {
						CU_ASSERT_EQUAL(
								isMovementExists(movements, movementCount, bingPos, bingPos - 1),
								right);
					}
					if (bingRankPos < 8 && bingPos >= 45) {
						CU_ASSERT_EQUAL(
								isMovementExists(movements, movementCount, bingPos, bingPos + 1),
								left);
					}
					if (bingPos < 81) {
						CU_ASSERT_EQUAL(
								isMovementExists(movements, movementCount, bingPos, bingPos + 9),
								top);
					}
				}
			}
		}
	}
}
void test_genRedCheKillingMovements() {

}
void test_genRedMaKillingMovements() {

}
void test_genRedPaoKillingMovements() {

}
void test_genBlackJiangKillingMovements() {

}
void test_genBlackXiangKillingMovements() {

}
void test_genBlackShiKillingMovements() {

}
void test_genBlackBingKillingMovements() {

}
void test_genBlackCheKillingMovements() {

}
void test_genBlackMaKillingMovements() {

}
void test_genBlackPaoKillingMovements() {

}

void BitBoardTestSetUp() {
	CU_pSuite pSuite = CU_add_suite("Suite_BitBoardTest", initBitBoardTestSuite,
			cleanBitBoardTestSuite);
	CU_add_test(pSuite, "test_maskInitialization", test_maskInitialization);
	CU_add_test(pSuite, "test_rotateMaskInitialization",
			test_rotateMaskInitialization);
	CU_add_test(pSuite, "test_jiangMovements", test_jiangMovements);
	CU_add_test(pSuite, "test_xiangMovements", test_xiangMovements);
	CU_add_test(pSuite, "test_shiMovements", test_shiMovements);
	CU_add_test(pSuite, "test_redBingMovements", test_redBingMovements);
	CU_add_test(pSuite, "test_blackBingMovements", test_blackBingMovements);
	CU_add_test(pSuite, "test_cheMovements", test_cheMovements);
	CU_add_test(pSuite, "test_maMovements", test_maMovements);
	CU_add_test(pSuite, "test_paoMovements", test_paoMovements);
	CU_add_test(pSuite, "test_genRedJiangKillingMovements",
			test_genRedJiangKillingMovements);
	CU_add_test(pSuite, "test_genRedXiangKillingMovements",
			test_genRedXiangKillingMovements);
	CU_add_test(pSuite, "test_genRedShiKillingMovements",
			test_genRedShiKillingMovements);
	CU_add_test(pSuite, "test_genRedBingKillingMovements",
			test_genRedBingKillingMovements);
}
